package hamaster.jpbc;

import static hamaster.jpbc.Messages.getString;
import static hamaster.jpbc.util.SwingUtil.setLocationCenter;
import static javax.swing.JOptionPane.showMessageDialog;
import hamaster.jpbc.crypt.CryptMethod;
import hamaster.jpbc.gui.ConfigPanel;
import hamaster.jpbc.gui.DecryptPanel;
import hamaster.jpbc.gui.DownIDPanel;
import hamaster.jpbc.gui.EncryptPanel;
import hamaster.jpbc.gui.VerifyPanel;
import hamaster.jpbc.gui.WelcomePanel;
import hamaster.jpbc.pbc.PBC;
import hamaster.jpbc.pbc.PublicParameter;
import hamaster.jpbc.userconfig.UserConfig;
import hamaster.jpbc.userconfig.UserConfigManager;
import it.unisa.dia.gas.plaf.jpbc.pairing.CurveParams;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;

/**
 * 程序的主入口点
 * @author <a href="mailto:wangyeee@gmail.com">Wang Ye</a>
 */
public class Main extends JFrame implements ActionListener, WindowListener {
	private static final long serialVersionUID = 1L;

	public final static int SYMMETRIC_KEY_LENGTH = 32;
	public final static int IBC_BLOCK_SIZE = 128;

	private static PublicParameter publicParameter;
	private static List<CryptMethod> methods;
	private static int blockSize;
	private static UserConfig userConfig;
	private static String idUrl;

	static {
		CurveParams params = new CurveParams();
		try {
			params.load(new FileInputStream(new File("a.param"))); //$NON-NLS-1$
			PBC.instance(params).getPairing().getZr().newRandomElement();
		} catch (Throwable t) {
			showMessageDialog(null, getString("Main.cannotloadlibpbc"), getString("Main.fatalerror"), JOptionPane.ERROR_MESSAGE);  //$NON-NLS-1$//$NON-NLS-2$
			t.printStackTrace();
			System.exit(1);
		}
		if (publicParameter == null) {
			Properties properties = new Properties();
			try {
				properties.load(new FileInputStream(new File("config.properties"))); //$NON-NLS-1$
				publicParameter = new PublicParameter(properties, null);
				String totalMethods = properties.getProperty("totalmethods"); //$NON-NLS-1$
				String[] ms = totalMethods.split(";"); //$NON-NLS-1$
				methods = new ArrayList<CryptMethod>();
				for (String me : ms) {
					CryptMethod method = new CryptMethod();
					method.setId(me);
					method.setName(properties.getProperty(me + ".dispname")); //$NON-NLS-1$
					method.setDescription(properties.getProperty(me + ".description")); //$NON-NLS-1$
					methods.add(method);
				}
				try {
					blockSize = Integer.parseInt(properties.getProperty("ioblocksize")); //$NON-NLS-1$
				} catch (NumberFormatException e) {
					blockSize = 1024;
				}
				idUrl = properties.getProperty("idurl"); //$NON-NLS-1$
			} catch (IOException e) {
			}
		}
	}

	private WelcomePanel welcomePanel;
	private EncryptPanel encryptPanel;
	private DecryptPanel decryptPanel;
	private VerifyPanel verifyPanel;
	private ConfigPanel configPanel;
	private JMenuBar menuBar;
	private JMenuItem encryption;
	private JMenuItem decryption;
	private JMenuItem exit;
	private JMenuItem setting;
	private JMenuItem about;
	private JMenuItem downloadID;
	private JMenuItem downloadKey;
	private JMenuItem help;

	public Main() {
		super(getString("Main.formTitle")); //$NON-NLS-1$
		setLayout(new BorderLayout());
		Thread loadcfg = new Thread(new UserConfigManager(this));
		loadcfg.start();
		menuBar = new JMenuBar();
		setJMenuBar(menuBar);
		JMenu fileMenu = new JMenu(Messages.getString("Main.8")); //$NON-NLS-1$
		JMenu subNew = new JMenu(Messages.getString("Main.9")); //$NON-NLS-1$
		encryption = new JMenuItem(Messages.getString("Main.10")); //$NON-NLS-1$
		decryption = new JMenuItem(Messages.getString("Main.11")); //$NON-NLS-1$
		subNew.add(encryption);
		subNew.add(decryption);
		exit = new JMenuItem(Messages.getString("Main.12")); //$NON-NLS-1$
		fileMenu.add(subNew);
		fileMenu.add(exit);
		JMenu settingMenu = new JMenu(Messages.getString("Main.13")); //$NON-NLS-1$
		setting = new JMenuItem(Messages.getString("Main.14")); //$NON-NLS-1$
		settingMenu.add(setting);
		JMenu serverMenu = new JMenu(Messages.getString("Main.15")); //$NON-NLS-1$
		downloadID = new JMenuItem(Messages.getString("Main.16")); //$NON-NLS-1$
		downloadKey = new JMenuItem(Messages.getString("Main.17")); //$NON-NLS-1$
		serverMenu.add(downloadID);
		// TODO 完成菜单
//		serverMenu.add(downloadKey);
		JMenu helpMenu = new JMenu(Messages.getString("Main.18")); //$NON-NLS-1$
		help = new JMenuItem(Messages.getString("Main.19")); //$NON-NLS-1$
		helpMenu.add(help);
		about = new JMenuItem(Messages.getString("Main.20")); //$NON-NLS-1$
		helpMenu.add(about);
		encryption.addActionListener(this);
		decryption.addActionListener(this);
		exit.addActionListener(this);
		setting.addActionListener(this);
		downloadID.addActionListener(this);
		downloadKey.addActionListener(this);
		help.addActionListener(this);
		about.addActionListener(this);
		menuBar.add(fileMenu);
		menuBar.add(settingMenu);
		menuBar.add(serverMenu);
		menuBar.add(helpMenu);
		welcomePanel = new WelcomePanel(this);
		add(welcomePanel, BorderLayout.CENTER);
		addWindowListener(this);
		setSize(600, 400);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocationCenter(this);
		setVisible(true);
	}

	public static void main(String[] args) {
		new Main();
	}

	public List<CryptMethod> getMethods() {
		return methods;
	}

	public String getMethodIdByName(String name) {
		for (CryptMethod method : methods) {
			if (method.getName().equalsIgnoreCase(name))
				return method.getId();
		}
		return name;
	}

	public static PublicParameter publicParameter() {
		return publicParameter;
	}

	public static int ioBlockSize() {
		return blockSize;
	}

	public VerifyPanel getVerifyPanel() {
		return verifyPanel;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == exit) {
			System.exit(0);
		}
		if (e.getSource() == about) {
			showAboutDialog();
			return;
		}
		if (e.getSource() == encryption) {
			showEncryptPanel();
			return;
		}
		if (e.getSource() == decryption) {
			showDecryptPanel();
			return;
		}
		if (e.getSource() == setting) {
			showSettingsPanel();
			return;
		}
		if (e.getSource() == downloadID) {
			showDownloadIDPanel();
			return;
		}
		if (e.getSource() == downloadKey) {
			showDownloadKeyPanel();
			return;
		}
		if (e.getSource() == help) {
			showHelpPanel();
		}
	}

	public void showAboutDialog() {
		JOptionPane.showMessageDialog(this, Messages.getString("Main.21"), Messages.getString("Main.22"), JOptionPane.INFORMATION_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
		// TODO 完成关于对话框设计
	}

	public void showHelpPanel() {
		JOptionPane.showMessageDialog(this, Messages.getString("Main.23"), Messages.getString("Main.24"), JOptionPane.INFORMATION_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
		// TODO 完成帮助对话框设计
	}

	public void showEncryptPanel() {
		encryptPanel = new EncryptPanel(this);
		Thread t = new Thread() {
			@Override
			public void run() {
				JDialog dialog = new JDialog(Main.this);
				dialog.add(encryptPanel);
				dialog.pack();
				dialog.setTitle(Messages.getString("Main.25")); //$NON-NLS-1$
				setLocationCenter(dialog);
				dialog.setVisible(true);
			}
		};
		t.start();
	}

	public void showDecryptPanel() {
		decryptPanel = new DecryptPanel(this);
		Thread t = new Thread() {
			@Override
			public void run() {
				JDialog dialog = new JDialog(Main.this);
				dialog.add(decryptPanel);
				dialog.pack();
				dialog.setTitle(Messages.getString("Main.26")); //$NON-NLS-1$
				setLocationCenter(dialog);
				dialog.setVisible(true);
			}
		};
		t.start();
	}

	public void showSettingsPanel() {
		Thread t = new Thread() {
			@Override
			public void run() {
				JDialog dialog = new JDialog(Main.this);
				configPanel = new ConfigPanel(Main.this, dialog);
				dialog.add(configPanel);
				dialog.pack();
				dialog.setTitle(Messages.getString("Main.27")); //$NON-NLS-1$
				setLocationCenter(dialog);
				dialog.setVisible(true);
			}
		};
		t.start();
	}

	public void showDownloadIDPanel() {
		Thread t = new Thread() {
			@Override
			public void run() {
				JDialog dialog = new JDialog(Main.this);
				DownIDPanel down = new DownIDPanel(dialog);
				dialog.add(down);
				dialog.setTitle(Messages.getString("Main.28")); //$NON-NLS-1$
				dialog.pack();
				setLocationCenter(dialog);
				dialog.setResizable(false);
				dialog.setVisible(true);
			}
		};
		t.start();
	}

	public void showDownloadKeyPanel() {
		// TODO 完成下载密钥对话框
	}

	public void setUserConfig(UserConfig userConfig) {
		Main.userConfig = userConfig;
	}

	public static UserConfig getUserConfig() {
		return userConfig;
	}

	public static String getIdUrl() {
		return idUrl;
	}

	@Override
	public void windowClosing(WindowEvent event) {
		// TODO 保存新的配置(如果配置被改变)
		File file = new File(new File(UserConfigManager.getConfigFolderName()), UserConfigManager.getConfigFileName());
		try {
			userConfig.store(file);
		} catch (IOException e) {
		}
	}

	@Override
	public void windowOpened(WindowEvent e) {}
	@Override
	public void windowClosed(WindowEvent e) {}
	@Override
	public void windowIconified(WindowEvent e) {}
	@Override
	public void windowDeiconified(WindowEvent e) {}
	@Override
	public void windowActivated(WindowEvent e) {}
	@Override
	public void windowDeactivated(WindowEvent e) {}
}
